package com.glsc.ngateway.platform.controller;

import com.glsc.ngateway.common.api.common.dto.PageQueryParamDto;
import com.glsc.ngateway.common.api.common.enums.PageConstant;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.api.platform.dto.user.RoleDto;
import com.glsc.ngateway.common.api.platform.resp.PlatformResponse;
import com.glsc.ngateway.common.base.annotation.PageAccessAnnotation;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.Role;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.Url;
import com.glsc.ngateway.platform.aspect.UserCache;
import com.glsc.ngateway.platform.service.RoleService;
import com.glsc.ngateway.platform.service.UrlService;
import com.glsc.ngateway.platform.utils.JsonTool;
import com.glsc.ngateway.platform.utils.SpecificationFactory;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 功能描述: <br>
 *
 * @author gaojc
 * @date 2020/9/3 13:16
 */
@RestController
@RequestMapping("/role")
public class RoleController {

    private RoleService roleService;
    private UrlService urlService;
    private UserCache userCache;
    private HttpServletRequest request;

    @Autowired
    public void setRoleService(RoleService roleService) {
        this.roleService = roleService;
    }

    @Autowired
    public void setUrlService(UrlService urlService) {
        this.urlService = urlService;
    }

    @Autowired
    public void setUserCache(UserCache userCache) {
        this.userCache = userCache;
    }

    @Autowired
    public void setRequest(HttpServletRequest request) {
        this.request = request;
    }

    @PageAccessAnnotation(operMenu = "权限管理-角色管理", operType = "新建", operDesc = "新建角色")
    @PostMapping("/create")
    @ApiOperation(value = "新增角色")
    public PlatformResponse<Void> create(@RequestBody Role role) {
        roleService.add(role);
        return PlatformResponse.successMsg("创建成功");
    }

    @PageAccessAnnotation(operMenu = "权限管理-角色管理", operType = "编辑", operDesc = "编辑角色")
    @PostMapping("/update")
    @ApiOperation(value = "更新角色信息")
    public PlatformResponse<Void> update(@RequestBody Role role) {
        roleService.update(role);
        return PlatformResponse.successMsg("更新成功");
    }

    @PageAccessAnnotation(operMenu = "权限管理-角色管理", operType = "权限分配", operDesc = "设置角色权限")
    @PostMapping("/seturls")
    @ApiOperation(value = "设置角色的权限")
    public PlatformResponse<Void> setUrls(@ApiParam(required = true, value = "角色设置权限") @RequestBody String jsonStr) {
        JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject();
        JsonElement roleIdE = json.get("roleId");
        if (null == roleIdE || roleIdE.getAsLong() < 0) {
            return PlatformResponse.failedMsg("roleId 参数错误");
        }
        Role role = roleService.findById(roleIdE.getAsLong());
        if (null == role) {
            return PlatformResponse.failedMsg("角色不存在");
        }
        JsonArray jsonArray = json.get("urls").getAsJsonArray();
        Set<Url> urls = new HashSet<>();
        jsonArray.forEach(object -> {
            long urlId = object.getAsJsonObject().get("urlId").getAsLong();
            Url url = urlService.findById(urlId);
            if (null != url) {
                urls.add(url);
            }
        });
        role.setUrls(urls);
        roleService.save(role);

        return PlatformResponse.successMsg("权限设置成功");
    }

    @PostMapping("/addusers")
    @ApiOperation(value = "为某个角色批量设置用户")
    public PlatformResponse<Void> addUsers(@ApiParam(required = true, value = "{\"roleId\": 1, \"userIds\": [1, 2, 3]}")
                                     @RequestBody Map<String, Object> map) {
        long roleId = Long.valueOf(String.valueOf(map.get("roleId")));
        List<Object> userIds = (List) map.get("userIds");
        roleService.addUsers(roleId, userIds.stream()
                .map(id -> Long.valueOf(String.valueOf(id)))
                .collect(Collectors.toList()));
        return PlatformResponse.successMsg("添加成功");
    }

    @PostMapping("/deleteusers")
    @ApiOperation(value = "为某个角色批量删除用户")
    public PlatformResponse<Void> deleteUsers(@ApiParam(required = true, value = "{\"roleId\": 1, \"userIds\": [1, 2, 3]}")
                                        @RequestBody Map<String, Object> map) {
        long roleId = Long.valueOf(String.valueOf(map.get("roleId")));
        List<Object> userIds = (List) map.get("userIds");
        roleService.deleteUsers(roleId, userIds.stream()
                .map(id -> Long.valueOf(String.valueOf(id)))
                .collect(Collectors.toList()));
        return PlatformResponse.successMsg("删除成功");
    }

    @PageAccessAnnotation(operMenu = "权限管理-角色管理", operType = "删除", operDesc = "删除角色")
    @PostMapping("/delete")
    @ApiOperation(value = "删除角色")
    public PlatformResponse<Void> delete(@RequestBody String uid) {
        Long id = JsonTool.parseJsonId(uid);
        if (id == null) {
            return PlatformResponse.failedMsg("id不能为空");
        }
        if (roleService.delete(id) == 1) {
            return PlatformResponse.successMsg("删除成功");
        } else {
            return PlatformResponse.failedMsg("未找到id=" + id + "的角色");
        }
    }

    @GetMapping("/findbyid")
    @ApiOperation(value = "根据id查找角色")
    public PlatformResponse<Role> findById(@RequestParam("id") long id) {
        Role role = roleService.findById(id);
        if (role == null) {
            return PlatformResponse.failedMsg("未找到id=" + id + "的角色");
        }
        return PlatformResponse.successData(role);
    }

    @GetMapping("/findListByAuthId")
    @ApiOperation(value = "根据权限id查询角色列表分页")
    public PlatformResponse<Page<Role>> findListByAuthId(
            @ApiParam(value = "权限id") @RequestParam("authId") long authId,
            @ApiParam(value = "角色名称") @RequestParam(value="name", required = false) String name,
            @ApiParam(value = "页码从1开始") @RequestParam(required = false) Integer pageNo,
            @ApiParam(value = "每页显示条数 默认10") @RequestParam(required = false) Integer pageSize
    ) {
        if (pageNo == null) {
            pageNo = 1;
        }
        if (pageSize == null) {
            pageSize = PageConstant.PageSize;
        }
        Map<String,Object> param = new HashMap();
        param.put("authId",authId);
        param.put("name",name);
        PageQueryParamDto<Map<String,Object>> pageParam = new PageQueryParamDto(param, pageNo, pageSize, new ArrayList<>());
        Page<Role> result  = roleService.findPageByAuthId(pageParam);
        return PlatformResponse.successData(result);
    }

    @PageAccessAnnotation(operMenu = "权限管理-用户管理", operType = "查询", operDesc = "角色列表")
    @GetMapping("/list")
    @ApiOperation(value = "查询所有角色")
    public PlatformResponse<List<Role>> list(@ApiParam(value = "角色名称") @RequestParam(required = false) String name) {
        if (name != null && name.isEmpty()) {
            name = null;
        }

        SpecificationFactory.SpecElement deletedE = new SpecificationFactory.SpecElement(SpecificationFactory.Type.EQ, "deleted", 0);
        SpecificationFactory.SpecElement nameE = new SpecificationFactory.SpecElement(SpecificationFactory.Type.LIKE, "name", name);
        Specification spec = SpecificationFactory.build(SpecificationFactory.OP.AND, deletedE, nameE);
        PlatformUserDto user = userCache.get(request);
        //去除ADMIN账号，此处代码未发现对逻辑的影响
        if (!"admin".equals(user.getUsername().toLowerCase())) {
            spec = spec.and((root, query, builder) ->
                    builder.notEqual(root.get("name"), "ROLE_ADMIN")
            );
        }
        List<Role> list = roleService.findAll(spec);
        return PlatformResponse.successData(list);
    }

    @PageAccessAnnotation(operMenu = "权限管理-角色管理", operType = "查询", operDesc = "角色列表")
    @GetMapping("/listpage")
    @ApiOperation(value = "查询角色分页")
    public PlatformResponse<Page<RoleDto>> listpage(
            @ApiParam(value = "角色名称") @RequestParam(required = false) String name,
            @ApiParam(value = "页码从1开始") @RequestParam(required = false) Integer pageNo,
            @ApiParam(value = "每页显示条数 默认10") @RequestParam(required = false) Integer pageSize) {
        if (name != null && name.isEmpty()) {
            name = null;
        }

        if (pageNo == null) {
            pageNo = 1;
        }
        if (pageSize == null) {
            pageSize = PageConstant.PageSize;
        }
        SpecificationFactory.SpecElement deletedE = new SpecificationFactory.SpecElement(SpecificationFactory.Type.EQ, "deleted", 0);
        SpecificationFactory.SpecElement nameE = new SpecificationFactory.SpecElement(SpecificationFactory.Type.LIKE, "name", name);
        Specification spec = SpecificationFactory.build(SpecificationFactory.OP.AND, deletedE, nameE);
        PlatformUserDto user = userCache.get(request);
        //去除ADMIN账号，此处代码未发现对逻辑的影响
        if (!"admin".equals(user.getUsername().toLowerCase())) {
            spec = spec.and((root, query, builder) ->
                    builder.notEqual(root.get("name"), "ROLE_ADMIN")
            );
        }
        Page<RoleDto> page = roleService.findPage(spec, pageNo, pageSize);
        return PlatformResponse.successData(page);
    }
}
